#pragma once
#include <set>
#include <string>
#include <cstring>
#include <cerrno>
#include <iostream>

#include <sys/epoll.h>

#include "Log.hpp"
namespace EpollerModule
{
    const static int defaultepfd = -1;
    const static int defaultsize = 128;

    class Epoller
    {
    public:
        Epoller(int epfd=defaultepfd)
            : _epfd(epfd)
        {
        }
        ~Epoller() {
            if(_epfd>=0)
            {
                close(_epfd);
            }
            lg.LogMessage(Info,"close ep_fd %d",_epfd);
        
        }

        void InitEpoller()
        {
            _epfd = ::epoll_create(defaultsize);
            if (_epfd < 0)
            {
                lg.LogMessage(Fatal, "epoll_create error,%d:%s", errno, std::strerror(errno));
                exit(1);
            }
            lg.LogMessage(Info, "epoll_create success! epfd %d", _epfd);
        }

        void AddEvent(int sockfd, uint32_t events)
        {
            _fd_list.insert(sockfd);

            struct epoll_event ev;
            ev.data.fd = sockfd; // 给用户看的
            ev.events = events;

            int n = ::epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
            if (n < 0)
            {
                lg.LogMessage(Warning, "epoll_ctr add events error,%d:%s", errno, strerror(errno));
                exit(2);
            }
        }

        void ModEvent(int sockfd, uint32_t events)
        {
            struct epoll_event ev;
            ev.data.fd = sockfd;
            ev.events = events;
            int n = ::epoll_ctl(_epfd, EPOLL_CTL_MOD, sockfd, &ev);
            if (n < 0)
            {
                lg.LogMessage(Warning, "epoll_ctr modifity events error,%d:%s", errno, strerror(errno));
                exit(2);
            }
        }

        void DelEvent(int sockfd)
        {
            _fd_list.erase(sockfd);

            int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if (n < 0)
            {
                lg.LogMessage(Warning, "epoll_ctr del events error,%d:%s", errno, strerror(errno));
                exit(2);
            }
        }

        int wait(struct epoll_event *events,int maxevents,int timeout)
        {
            int n=::epoll_wait(_epfd,events,maxevents,timeout);
            return n;
        }

        void DebugList()
        {
            std::cout<<"fd_list:";
            for(auto& fd:_fd_list)
            {
                std::cout<<fd<<" ";
            }
            std::cout<<std::endl;
        }

    private:
        int _epfd;
        std::set<int> _fd_list;
    };
}